package com.dongbao.core.rules.java;

import com.dongbao.core.base.CodeRulesCommonBase;
import com.dongbao.core.rules.CodeRulesBase;
import com.dongbao.entity.AwardedInfo;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.formatter.java.SimpleJavaBlock;
import com.intellij.psi.impl.source.PsiClassImpl;
import com.intellij.psi.impl.source.PsiFieldImpl;
import com.intellij.psi.impl.source.PsiParameterImpl;
import com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiElementFilter;
import com.intellij.psi.util.PsiTreeUtil;

import java.util.*;
import java.util.stream.Collectors;

/**
 *  Map操作请使用工具类操作,例如获取
 * */
public class MapOperationRules extends CodeRulesCommonBase implements CodeRulesBase {

    private Map<String,PsiElement> mapVariable = new HashMap<String,PsiElement>();

    public MapOperationRules(VirtualFile afterFile,PsiFile psiFile,Project project) {
        super(afterFile,psiFile,project);
        this.code = "A010";
        this.level = "A";
    }

    /**
     * 执行规则判断
     * */
    @Override
    public void run(List<AwardedInfo> deduction) {

        for(PsiClassImpl psiClass:psiClassImpls){
            /* 获取所有方法 */
            PsiMethod[] allMethods = psiClass.getMethods();
            PsiElement[] classAllVariables = getClassAllVariables(psiClass);
            for(PsiElement classAllVariable:classAllVariables){
                    String variableType = "";
                    final String variableTypeFinal=variableType;
                        /* 查找整个项目使用了这个对象的地方(需要修改成当前类文件用到的地方) */
//                        Collection<PsiReference> allPsiReference = ReferencesSearch.search(classAllVariable, GlobalSearchScope.allScope(psiClass.getProject()),true).findAll();
                        Collection<PsiReference> allPsiReference = ReferencesSearch.search(classAllVariable, GlobalSearchScope.fileScope(psiClass.getContainingFile()),true).findAll();
                        /* 找到使用了get方法的引用 */

                        List<PsiReference> getColle = allPsiReference.stream().filter(item -> {
                            return item.getElement().getParent().getText().contains("get");
                        }).collect(Collectors.toList());
                        /* 对使用了get方式获取Map值的方法进行提示 */
                        if(!getColle.isEmpty()){
                            for(PsiReference errorRow:getColle){
                                PsiElement rowElement = errorRow.getElement().getParent();
                                Document document = PsiDocumentManager.getInstance(psiClass.getProject()).getDocument(psiClass.getContainingFile());
                                int lineNumber = document.getLineNumber(rowElement.getTextOffset());

                                packDeduction(
                                        deduction,
                                        psiClass.getName(),
                                        psiPackageStatements.get(0).getPackageName(),
                                        "",
                                        String.format("Map的获取值的方法推荐使用工具类MapUtil方法获取"),lineNumber,lineNumber);
                            }
                        }
                        System.out.println("找到了声明的Map变量");
            }
        }
    }

    /**
     * 获取类中所有声明的变量,包括方法中声明的
     * */
    public static PsiElement[] getClassAllVariables(PsiElement element){
        List<String> keys = new ArrayList<String>();
        keys.add("PsiType:Map");
        keys.add("PsiType:HashMap");
        PsiElement[] variables = PsiTreeUtil.collectElements(element, new PsiElementFilter() {
            public boolean isAccepted(PsiElement e) {
                if (e instanceof PsiVariable) {
                    String variableType="";
                    List<String> mapColl = null;
                    if(e instanceof PsiLocalVariableImpl){
                        variableType = ((PsiLocalVariableImpl) e).getType().toString();
                    }else if(e instanceof PsiFieldImpl){
                        variableType = ((PsiFieldImpl) e).getType().toString();
                    }else if(e instanceof PsiParameterImpl){
                        variableType = ((PsiParameterImpl) e).getType().toString();
                    }
                    String finalVariableType = variableType;
                    mapColl = keys.stream().filter(item -> finalVariableType.contains(item)).collect(Collectors.toList());
                    if(!mapColl.isEmpty()){
                        return true;
                    }
                }
                return false;
            }
        });
        return variables;
    }

    @Override
    public String describe() {
        return "系统公共方法和工具类";
    }
}
